package alipay

import (
	"asystem/pays/config"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/smartwalle/alipay/v3"
	"log"
	"net/http"
)

const PrivateKey = "MIIEowIBAAKCAQEAsPnxwOj/BAiIKjju4WpvWFD+OhqzFoigydrlDrkiY1WWsdt0nw/X9Xu/MyWE1GPJHn/robnEsPDNyaLhIaV4COuyTcqXBTqIuxtfntg79FVNcCT2RRcYdPbBLvBBalJeyjf0DuorgZ5USX3dc4s08JszzBTyHhN/yw9gne57NNXHYk7BoDcs0jLZBQDwaF09pqm2FBgM2i10nH659HK65nkxSxfh5xUMfwoXMz28/PzzvUWK/+nEtVsOxWqJnT9n6f3eDY9pYvmGGrJZjP+ohkT/6TwtbWtslZCxfoYezoj1CwvpF6wWLzgKHaAIO34Qm5eg7h43LSdbDZqt5wRZGQIDAQABAoIBABGNeLDNax2XSwoFA4xP5iM4RT62DzUY7/mVQEqpigOYJY4WWga8p4qtb1U/T2FRVE02GsS7jAqQl5h8EyAnLTSVS+XzRe860vzbxiwW/jtJipio0dQgakiPgLGLGrHU4Znk2svv5cjBT1LKrQAcum9ytTx0h178SBx3tfl0AbxHnVL6u9+KEGMtKFb6WdLlsmd6gvaEPz1cIQsdl0+njGq359yanSVNLYnuDw8fm4l9+j0IdVdFRJOw7+2/gd2z0xazyoYnMZmiQn/+h683avWAu109xiqjBs12NxFmB4hSL9SwFbcMR/uVuVAXnYNw7gtiYFUQVjNeSodf8De0tgECgYEA57f5tjxsov1Gthboywtu+EWUTgdXyYEB95Pf7D3i4M0r47Xb/i4LKCKgTwqSR8aWG2OKfucg06qhsVmNzbD7C/DRi69/gWqKJhDM5apdcRIJPQtKUTzmqX/rqkvyBK0dowSB4QFxIeGPz4ZZV64uY90LRiGHu8PZZ2N9SjfwF3ECgYEAw4V3Rojk2ael5LJwVf5E3awxgnnMe15kvN3S2my4ps8/BeID5PyH9+5PRsXyFn0TrOirW4HCpWK6e5AeSQectQpjkcdjQPJ0QOowxMqQzTyicS8wlXBGUfPkLh/yHalOpHZlEq0S0fcZ77BJxvWpunAT2VMZbO3uuU9GheI+GCkCgYAgmyzSTfJjhQxcNyEO4U7+NJxH1pSt0C98rRxHW/X++CAC7OZGACilvymbtbsbyn/43qrwbImb/1i9YgKoPQ02gu6Zn1pr1ZgW/yo17yEy9fzC0EHm6JD0rQF2dzVZHxsag1nbVZ6by+e2pgsQYXw5pTMe7TzyWP7Qo5lPxktMoQKBgH8JuyQTUk6xhTKBVkgpe+lkNo8GQHxwKpgksRnGxntr8RELd2hTRK0tJElh2BgQkLYqPxynxSbcbTpXu7XLwmBHLcbMfIr4fdynzaQv0cHogct00+ZlGuuowjvN+eyX00c8vhNSbQYLvchlDKq/d9ZxeBQe0EhcmF3DSpk3FQ1xAoGBALlTRPwWSVcZvvcQn/UpkPD7qqxqHAYUDT3tVkaTqUvCk1WI26+R/4ETr+qzLaG41frPhXFhMbpXyo0JkrO2YrP9qS7mKo/5eEaFmp4lq6S+1EGozQc0z7ppmYfh6K1rWYkGUgoXKiYys6uF1ndu9eZRM0gwTTCe8T1p+Q4ri0EF"

type PayInterface interface {
	Pay(c *gin.Context)
	AliCallback(c *gin.Context)
	AliNotify(c *gin.Context)
}

type AliPay struct {
	AliClient *alipay.Client
}

func InitAliClient() (aliClient *AliPay, err error) {
	aliCfg, err := config.NewReadCfg().LoadCfg(config.CfgPath)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("读取配置文件出错，错误代码：%v", err))
	}
	client, err := alipay.New(aliCfg.Alipay.AliAppid, PrivateKey, aliCfg.Alipay.AliIsProduction)
	if err != nil {
		fmt.Println("初始化客户端出错，错误代码：", err)
		return nil, errors.New(fmt.Sprintf("初始化客户端出错，错误代码：%v", err))
	}
	// 使用支付宝证书 aliappcertpublickeyfile
	if err = client.LoadAppPublicCertFromFile(aliCfg.Alipay.AliAppCertPublicKeyFile); err != nil {
		log.Println("加载阿里公钥证书发生错误", err)
		return
	}
	if err = client.LoadAliPayRootCertFromFile(aliCfg.Alipay.AliPayRootCert); err != nil {
		log.Println("加载根证书发生错误", err)
		return
	}
	if err = client.LoadAliPayPublicCertFromFile(aliCfg.Alipay.AliPayCertPublicKeyRSA2); err != nil {
		log.Println("加载应用证书发生错误", err)
		return
	}
	return &AliPay{AliClient: client}, nil
}

func (a *AliPay) Pay(c *gin.Context) {
	// 自己根据前端数据拼接 todo 获取前端的数据的单号和价格
	orderNo := c.Query("order")
	//createDate := c.Query("create")
	//goods := c.Query("goods")
	gas := c.Query("gas")
	//fmt.Println(orderNo, createDate, goods, gas, "====================================================")

	var tradeNo = orderNo

	aliCfg, err := config.NewReadCfg().LoadCfg(config.CfgPath)
	if err != nil {
		fmt.Println("读取配置文件错误，错误代码", err)
		return
	}
	var p = alipay.TradePagePay{}
	fmt.Printf(aliCfg.Alipay.AliReturnUrl, "*******************************************************\n")
	p.NotifyURL = aliCfg.Alipay.AliNotifyUrl
	p.ReturnURL = aliCfg.Alipay.AliReturnUrl
	p.Subject = aliCfg.Alipay.AliSubject + tradeNo
	p.OutTradeNo = tradeNo
	p.TotalAmount = gas // 价格从前端传入
	p.ProductCode = "FAST_INSTANT_TRADE_PAY"

	url, _ := a.AliClient.TradePagePay(p)
	//fmt.Println(url, "<======================================================")
	c.JSON(200, gin.H{"success": url.String(), "errMsg": ""})
	//c.Redirect(http.StatusTemporaryRedirect, url.String())
}

func (a *AliPay) AliNotify(c *gin.Context) {
	c.Request.ParseForm()

	ok, err := a.AliClient.VerifySign(c.Request.Form)
	if err != nil {
		log.Println("异步通知验证签名发生错误", err)
		return
	}

	if ok == false {
		log.Println("异步通知验证签名未通过")
		return
	}

	log.Println("异步通知验证签名通过")

	var outTradeNo = c.Request.Form.Get("out_trade_no")
	var p = alipay.TradeQuery{}
	p.OutTradeNo = outTradeNo
	rsp, err := a.AliClient.TradeQuery(p)
	if err != nil {
		log.Printf("异步通知验证订单 %s 信息发生错误: %s \n", outTradeNo, err.Error())
		return
	}
	if rsp.IsSuccess() == false {
		log.Printf("异步通知验证订单 %s 信息发生错误: %s-%s \n", outTradeNo, rsp.Content.Msg, rsp.Content.SubMsg)
		return
	}
	fmt.Printf("订单 %s 支付成功<-------------------------------------------------", outTradeNo)
	log.Printf("订单 %s 支付成功 \n", outTradeNo)
}

func (a *AliPay) AliCallback(c *gin.Context) {
	c.Request.ParseForm()
	var outTradeNo = c.Request.Form.Get("out_trade_no")
	var p = alipay.TradeQuery{}
	p.OutTradeNo = outTradeNo
	rsp, err := a.AliClient.TradeQuery(p)
	if err != nil {
		c.String(http.StatusBadRequest, "验证订单 %s 信息发生错误: %s", outTradeNo, err.Error())
		return
	}
	if rsp.IsSuccess() == false {
		c.String(http.StatusBadRequest, "验证订单 %s 信息发生错误: %s-%s", outTradeNo, rsp.Content.Msg, rsp.Content.SubMsg)
		return
	}
	fmt.Printf("订单 %s 支付成功<==================================================", outTradeNo)
	c.String(http.StatusOK, "订单 %s 支付成功", outTradeNo)
}
